{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from tensorflow import keras"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.0.0-rc0\n"
     ]
    }
   ],
   "source": [
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "BATCH_SIZE = 256"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "BUFFER_SIZE = 60000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "EPOCHES = 300"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "OUTPUT_DIR = \"img\" # The output directory where the images of the generator a stored during training\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "mnist = keras.datasets.mnist\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "(train_images, train_labels), (test_images, test_labels) = mnist.load_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 0, 4, ..., 5, 6, 8], dtype=uint8)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 28, 28)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_images.shape\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x13389d950>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(train_images[1], cmap = \"gray\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_images = train_images.astype(\"float32\")\n",
    "train_images = (train_images - 127.5) / 127.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_dataset = tf.data.Dataset.from_tensor_slices(train_images.reshape(train_images.shape[0],784)).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Generator(keras.Model):\n",
    "    \n",
    "    def __init__(self, random_noise_size = 100):\n",
    "        super().__init__(name='generator')\n",
    "        #layers\n",
    "        self.input_layer = keras.layers.Dense(units = random_noise_size)\n",
    "        self.dense_1 = keras.layers.Dense(units = 128)\n",
    "        self.leaky_1 =  keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        self.dense_2 = keras.layers.Dense(units = 128)\n",
    "        self.leaky_2 = keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        self.dense_3 = keras.layers.Dense(units = 256)\n",
    "        self.leaky_3 = keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        self.output_layer = keras.layers.Dense(units=784, activation = \"tanh\")\n",
    "        \n",
    "    def call(self, input_tensor):\n",
    "        ## Definition of Forward Pass\n",
    "        x = self.input_layer(input_tensor)\n",
    "        x = self.dense_1(x)\n",
    "        x = self.leaky_1(x)\n",
    "        x = self.dense_2(x)\n",
    "        x = self.leaky_2(x)\n",
    "        x = self.dense_3(x)\n",
    "        x = self.leaky_3(x)\n",
    "        return  self.output_layer(x)\n",
    "    \n",
    "    def generate_noise(self,batch_size, random_noise_size):\n",
    "        return np.random.uniform(-1,1, size = (batch_size, random_noise_size))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits = True)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generator_objective(dx_of_gx):\n",
    "    # Labels are true here because generator thinks he produces real images. \n",
    "    return cross_entropy(tf.ones_like(dx_of_gx), dx_of_gx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "generator = Generator()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:Layer generator is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because it's dtype defaults to floatx.\n",
      "\n",
      "If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.\n",
      "\n",
      "To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "fake_image = generator(np.random.uniform(-1,1, size =(1,100)))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "fake_image = tf.reshape(fake_image, shape = (28,28))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x1375c5810>"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(fake_image, cmap = \"gray\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Discriminator(keras.Model):\n",
    "    def __init__(self):\n",
    "        super().__init__(name = \"discriminator\")\n",
    "        \n",
    "        #Layers\n",
    "        self.input_layer = keras.layers.Dense(units = 784)\n",
    "        self.dense_1 = keras.layers.Dense(units = 128)\n",
    "        self.leaky_1 =  keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        self.dense_2 = keras.layers.Dense(units = 128)\n",
    "        self.leaky_2 = keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        self.dense_3 = keras.layers.Dense(units = 128)\n",
    "        self.leaky_3 = keras.layers.LeakyReLU(alpha = 0.01)\n",
    "        \n",
    "        self.logits = keras.layers.Dense(units = 1)  # This neuron tells us if the input is fake or real\n",
    "    def call(self, input_tensor):\n",
    "          ## Definition of Forward Pass\n",
    "        x = self.input_layer(input_tensor)\n",
    "        x = self.dense_1(x)\n",
    "        x = self.leaky_1(x)\n",
    "        x = self.leaky_2(x)\n",
    "        x = self.leaky_3(x)\n",
    "        x = self.leaky_3(x)\n",
    "        x = self.logits(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "discriminator = Discriminator()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def discriminator_objective(d_x, g_z, smoothing_factor = 0.9):\n",
    "    \"\"\"\n",
    "    d_x = real output\n",
    "    g_z = fake output\n",
    "    \"\"\"\n",
    "    real_loss = cross_entropy(tf.ones_like(d_x) * smoothing_factor, d_x) # If we feed the discriminator with real images, we assume they all are the right pictures --> Because of that label == 1\n",
    "    fake_loss = cross_entropy(tf.zeros_like(g_z), g_z) # Each noise we feed in are fakes image --> Because of that labels are 0\n",
    "    \n",
    "    total_loss = real_loss + fake_loss\n",
    "    \n",
    "    return total_loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "generator_optimizer = keras.optimizers.RMSprop()\n",
    "discriminator_optimizer = keras.optimizers.RMSprop()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tf.function()\n",
    "def training_step(generator: Discriminator, discriminator: Discriminator, images:np.ndarray , k:int =1, batch_size = 32):\n",
    "    for _ in range(k):\n",
    "         with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:\n",
    "            noise = generator.generate_noise(batch_size, 100)\n",
    "            g_z = generator(noise)\n",
    "            d_x_true = discriminator(images) # Trainable?\n",
    "            d_x_fake = discriminator(g_z) # dx_of_gx\n",
    "\n",
    "            discriminator_loss = discriminator_objective(d_x_true, d_x_fake)\n",
    "            # Adjusting Gradient of Discriminator\n",
    "            gradients_of_discriminator = disc_tape.gradient(discriminator_loss, discriminator.trainable_variables)\n",
    "            discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) # Takes a list of gradient and variables pairs\n",
    "            \n",
    "              \n",
    "            generator_loss = generator_objective(d_x_fake)\n",
    "            # Adjusting Gradient of Generator\n",
    "            gradients_of_generator = gen_tape.gradient(generator_loss, generator.trainable_variables)\n",
    "            generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "seed = np.random.uniform(-1,1, size = (1, 100)) # generating some noise for the training\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Just to make sure the output directory exists..\n",
    "import os\n",
    "if not os.path.exists(OUTPUT_DIR):\n",
    "    os.makedirs(OUTPUT_DIR)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "def training(dataset, epoches):\n",
    "    for epoch in range(epoches):\n",
    "        for batch in dataset: \n",
    "            training_step(generator, discriminator, batch ,batch_size = BATCH_SIZE, k = 1)\n",
    "            \n",
    "        ## After ith epoch plot image \n",
    "        if (epoch % 50) == 0: \n",
    "            fake_image = tf.reshape(generator(seed), shape = (28,28))\n",
    "            print(\"{}/{} epoches\".format(epoch, epoches))\n",
    "            #plt.imshow(fake_image, cmap = \"gray\")\n",
    "            plt.imsave(\"{}/{}.png\".format(OUTPUT_DIR,epoch),fake_image, cmap = \"gray\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/ops/nn_impl.py:183: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "0/300 epoches\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<timed eval>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-36-3e847f567226>\u001b[0m in \u001b[0;36mtraining\u001b[0;34m(dataset, epoches)\u001b[0m\n\u001b[1;32m      2\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0mepoch\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mepoches\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mbatch\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdataset\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m             \u001b[0mtraining_step\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerator\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdiscriminator\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch\u001b[0m \u001b[0;34m,\u001b[0m\u001b[0mbatch_size\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBATCH_SIZE\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m         \u001b[0;31m## After ith epoch plot image\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m    413\u001b[0m       \u001b[0;31m# In this case we have created variables on the first call, so we run the\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    414\u001b[0m       \u001b[0;31m# defunned version which is guaranteed to never create variables.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 415\u001b[0;31m       \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateless_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# pylint: disable=not-callable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    416\u001b[0m     \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateful_fn\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    417\u001b[0m       \u001b[0;31m# In this case we have not created variables on the first call. So we can\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m   1820\u001b[0m     \u001b[0;34m\"\"\"Calls a graph function specialized to the inputs.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1821\u001b[0m     \u001b[0mgraph_function\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maybe_define_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1822\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mgraph_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_filtered_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# pylint: disable=protected-access\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1823\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1824\u001b[0m   \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m_filtered_call\u001b[0;34m(self, args, kwargs)\u001b[0m\n\u001b[1;32m   1139\u001b[0m          if isinstance(t, (ops.Tensor,\n\u001b[1;32m   1140\u001b[0m                            resource_variable_ops.BaseResourceVariable))),\n\u001b[0;32m-> 1141\u001b[0;31m         self.captured_inputs)\n\u001b[0m\u001b[1;32m   1142\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1143\u001b[0m   \u001b[0;32mdef\u001b[0m \u001b[0m_call_flat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcaptured_inputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcancellation_manager\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[1;32m   1222\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1223\u001b[0m       flat_outputs = forward_function.call(\n\u001b[0;32m-> 1224\u001b[0;31m           ctx, args, cancellation_manager=cancellation_manager)\n\u001b[0m\u001b[1;32m   1225\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1226\u001b[0m       \u001b[0mgradient_name\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_delayed_rewrite_functions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[1;32m    509\u001b[0m               \u001b[0minputs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    510\u001b[0m               \u001b[0mattrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"executor_type\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexecutor_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"config_proto\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfig\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 511\u001b[0;31m               ctx=ctx)\n\u001b[0m\u001b[1;32m    512\u001b[0m         \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    513\u001b[0m           outputs = execute.execute_with_cancellation(\n",
      "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py\u001b[0m in \u001b[0;36mquick_execute\u001b[0;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[1;32m     59\u001b[0m     tensors = pywrap_tensorflow.TFE_Py_Execute(ctx._handle, device_name,\n\u001b[1;32m     60\u001b[0m                                                \u001b[0mop_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m                                                num_outputs)\n\u001b[0m\u001b[1;32m     62\u001b[0m   \u001b[0;32mexcept\u001b[0m \u001b[0mcore\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_NotOkStatusException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     63\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mname\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "%%time\n",
    "training(train_dataset, EPOCHES)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://github.com/MonteChristo46/GAN-Notebooks/blob/master/GAN.ipynb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
